import { Callout } from 'nextra/components'
import BadgeGroup, { UniverTypes } from '@/components/BadgeGroup'

# 在 JavaScript 中扩展 Univer

<BadgeGroup values={[UniverTypes.GENERAL]} value={UniverTypes.GENERAL} />

<Callout>
  如果发现在部分集成了 TypeScript 支持的项目中，装饰器并没有正常工作的话（通常可能是因为 babel 相关的装饰器插件实现与 TypeScript 的不一致），也可以考虑使用这种方式来替代装饰器。
</Callout>

为了便于开发，Univer 使用了大量的 [TypeScript 装饰器](https://www.typescriptlang.org/docs/handbook/decorators.html)语法来声明依赖注入关系。

因此我们当然推荐你首先使用 TypeScript，但如果你不熟悉 TypeScript 或者受制于其他原因，你也可以使用 JavaScript 来扩展 Univer。当然，这并不是一件容易的事情，因为你可能需要了解 Univer 的内部机制以及如何使用 JavaScript 来实现 TypeScript 中的装饰器。

在 Univer 的文档中，最常见到的装饰器分别是由 [`@wendellhu/redi`](https://redi.wendell.fun) 提供的参数装饰器（Parameter Decorators）和由 `@univerjs/core` 提供的 `OnLifecycle` 类装饰器（Class Decorators）。这里将介绍如何在 JavaScript 中替代这两种装饰器。

## 参数装饰器

`@wendellhu/redi` 提供了 `setDependencies` 方法，用于在 JavaScript 中显示地声明依赖。例如：

```diff
import { Plugin, ICommandService, UniverInstanceType } from '@univerjs/core'
- import { Inject, Injector } from '@wendellhu/redi'
+ import { Injector, setDependencies } from '@wendellhu/redi'

export class MyPlugin extends Plugin {
  static override type = UniverInstanceType.UNIVER_UNKNOWN
  static override pluginName = 'MY_PLUGIN_NAME'

-  constructor(@Inject(Injector) protected readonly _injector: Injector, @ICommandService private readonly _commandService: ICommandService) {
+  constructor(_injector, _commandService) {
    super()

+   this._injector = _injector
+   this._commandService = _commandService
  }

-  override onStarting(injector: Injector): void {
+  override onStarting(injector) {
-    ([[ConfigService]] as Dependency[]).forEach(d => injector.add(d))
+    [[ConfigService]].forEach(d => injector.add(d))
  }
}

+ setDependencies(MyPlugin, [Injector, ICommandService])
```

参考：https://redi.wendell.fun/zh-CN/docs/javascript

## 类装饰器 `OnLifecycle`

`OnLifecycle` 类装饰器用于声明生命周期。`@univerjs/core` 中提供了 `runOnLifecycle` 方法，用于在 JavaScript 中显示地声明生命周期。例如：

```diff
- import { Disposable, LifecycleStages, OnLifecycle } from '@univerjs/core'
+ import { Disposable, LifecycleStages, runOnLifecycle } from '@univerjs/core'

- @OnLifecycle(LifecycleStages.Steady, MYController)
export class MYController extends Disposable {
}

+ runOnLifecycle(LifecycleStages.Steady, MYController)
```
